﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using TeacherHelp.DAL;
using TeacherHelp.Model;

namespace TeacherHelp.BLL
{
    public class TestManager
    {
        private readonly TestService _testService;
        private readonly TestInfoService _testInfoServiec;
        private readonly TeacherLinkGradeService _teacherLinkGradeService;

        public TestManager()
        {
            _testService = new DAL.TestService();
            _testInfoServiec = new DAL.TestInfoService();
            _teacherLinkGradeService = new TeacherLinkGradeService();
        }

        /// <summary>
        /// 获取考试结果
        /// </summary>
        /// <param name="subjectName"></param>
        /// <param name="date"></param>
        /// <param name="userId"></param>
        /// <param name="isTeacher"></param>
        /// <returns></returns>
        public List<ViewModel.TestResult> GetTestResult(string subjectName = null, string date = null, int? userId = null, bool isTeacher = false, string stuName = null)
        {
            string sql = _testService.GetTestResultAllSQL();

            if (!string.IsNullOrEmpty(subjectName) && subjectName != "全部")
                sql += _testService.GetWhereSubjectNameSQL(subjectName);

            if (!string.IsNullOrEmpty(date))
                sql += _testService.GetWhereDateSQL(date);

            if (!string.IsNullOrEmpty(stuName) && stuName != "全部")
                sql += _testInfoServiec.GetWhereStuNameSQL(stuName);

            if (userId != null)
            {
                if (isTeacher)//是老师
                {
                    //根据老师获取所管理的学生
                    var studentIdListSQL = _teacherLinkGradeService.GetAllStudentIdByTeacherId(userId.ToInt());
                    sql += _testService.GetWhereUserIdSQL(studentIdListSQL);
                }
                else//不是老师
                {
                    sql += _testService.GetWhereUserIdSQL(userId.ToString());
                }
            }
            sql += _testInfoServiec.GetOrderByDesc();
            return DBHelper.GetListModel<ViewModel.TestResult>(sql);
        }

        /// <summary>
        /// 考试提交
        /// </summary>
        /// <param name="testExercise">考试题目信息</param>
        /// <param name="maxSocre">最大分值</param>
        /// <param name="subjectId">科目Id</param>
        public double TestSubmit(List<ViewModel.TestExercises> testExercise, int? UserId, int? subjectId, ref int testId, DateTime? startTime = null, DateTime? endTime = null, int maxSocre = 100)
        {

            double score = 0;//分数

            try
            {
                Log.Info("正在计算分值..");
                double scoreValue = maxSocre / testExercise.Count;//计算分值

                Log.Info("正在进行题目整理..");
                List<Model.TestInfo> testResultList = new List<Model.TestInfo>();
                foreach (var exeItem in testExercise)
                {
                    Model.TestInfo testInfo = new Model.TestInfo();

                    var answer = string.Join(",", exeItem.answerList.OrderBy(m => m));
                    var select = string.Join(",", exeItem.selectList.OrderBy(m => m));

                    //记录题目答题过程
                    testInfo.Answer = answer;
                    testInfo.SelectResult = select;
                    testInfo.ExercisesId = exeItem.Id;

                    if (answer == select)//回答正确
                    {
                        score += scoreValue;
                        testInfo.IsNan = 1;
                    }
                    testResultList.Add(testInfo);
                }

                Log.Info("正在进行考试整理..");
                var result = new Model.Test
                {
                    StartTime = startTime,
                    EndTime = endTime,
                    SubjectsId = subjectId,
                    UserId = UserId,
                    Score = score.ToInt()
                };

                Log.Info("正在进行写入考试和考试详情的SQL操作..");
                string testSql = SQLBuilder.GetInsertSQLByModel(result) + SQLBuilder.GetIdentity();
                testId = DBHelper.ExecuteScalar(testSql).ToInt();

                var testInfoSql = new StringBuilder(200);

                foreach (var item in testResultList)
                {
                    item.TestId = testId;
                    testInfoSql.AppendLine(SQLBuilder.GetInsertSQLByModel(item));
                }

                int rows = DBHelper.ExecuteNonQuery(testInfoSql.ToString());
                if (rows <= 0)
                {
                    Log.Info("写入考试和考试详情的SQL操作受写入失败 rows=" + rows);
                }
            }
            catch (Exception ex)
            {
                Log.Error("考试提交时出现异常！", ex);
            }
            return score;
        }

        /// <summary>
        /// 生成考试详情html
        /// </summary>
        /// <param name="id"></param>
        public void BuilderTestInfoHTML(string id)
        {
            var url = System.Environment.CurrentDirectory + "\\temp";

            //如果文件夹不存在
            try
            {
                if (!Directory.Exists(url))
                {
                    Directory.CreateDirectory(url);//创建文件夹
                    File.SetAttributes(url, FileAttributes.Hidden);//隐藏
                }

                //加密考试详情对应的id 生成文件名
                var fileName = Util.MD5Helper.encrypt(id.ToString());
                url += "\\" + fileName + ".html";

                //如果html文件不存在
                if (!File.Exists(url))
                {
                    Model.Test test = GetTest(id);//获取考试记录
                    List<ViewModel.TestInfo> testInfo = GetTestInfo(id);//获取考试详情

                    string content = File.OpenText(System.Environment.CurrentDirectory + "\\Tempalate\\testInfo.html").ReadToEnd();

                    content = htmlBuilder(content, test, testInfo);
                    File.WriteAllText(url, content);//创建文件并写入
                    File.SetAttributes(url, FileAttributes.ReadOnly);//只读
                }

                //使用默认浏览器打开指定html文件
                System.Diagnostics.Process.Start(url);
            }
            catch (Exception ex)
            {
                Log.Error("生成考试详情html文本时出现异常！", ex);
            }
        }

        /// <summary>
        /// 获取考试详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private List<ViewModel.TestInfo> GetTestInfo(string id)
        {
            var sql = _testInfoServiec.GetTestInfoSQL() + _testInfoServiec.GetWhereTestIdSQL(id);
            var result = DBHelper.GetListModel<ViewModel.TestInfo>(sql);
            return result;
        }

        /// <summary>
        /// 获取考试信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private Test GetTest(string id)
        {
            var sql = _testService.GetTestSQL() + _testService.GetWhereIdSQL(id);
            var result = DBHelper.GetOneModel<Test>(sql);
            return result;
        }

        /// <summary>
        /// html文本生成器
        /// </summary>
        /// <param name="content"></param>
        /// <param name="test"></param>
        /// <param name="testInfo"></param>
        /// <returns></returns>
        private string htmlBuilder(string content, Test test, List<ViewModel.TestInfo> testInfo)
        {
            StringBuilder sb = new StringBuilder(30000);

            int i = 1;//题目序号
            int WrongTopicnNmber = 0;//错题数
            foreach (var info in testInfo)
            {
                //获取题目HTML文本
                sb.AppendLine(GetExercisesHtml(info, i++));

                if (info.IsNan == 0) WrongTopicnNmber++;
            }

            content = content.Replace("{{WrongTopicnNmber}}", WrongTopicnNmber.ToString());//错题数
            content = content.Replace("{{Score}}", test.Score.ToString());//分数          
            content = content.Replace("{{Content}}", "\r\n" + sb.ToString() + "\r\n");

            return content;
        }

        /// <summary>
        /// 获取题目的答题信息html
        /// </summary>
        /// <param name="info"></param>
        /// <param name="exercisesIndex"></param>
        /// <returns></returns>
        private string GetExercisesHtml(ViewModel.TestInfo info, int exercisesIndex)
        {
            StringBuilder html = new StringBuilder(600);
            html.AppendLine($"           <div class=\"info\">");
            html.AppendLine($"                <h4>");
            html.AppendLine($"                    第 {exercisesIndex} 题 ({info.exercisesType})");
            html.AppendLine($"                    <label class=\"topSelect\">你的选择：<span class=\"{(info.IsNan == 1 ? "blue" : "red")}\">{(string.IsNullOrWhiteSpace(info.SelectResult) ? "未选择" : info.SelectResult)}</span></label>");
            html.AppendLine($"                    <label class=\"answer\">答案：<span class=\"{(info.IsNan == 1 ? "blue" : "red")}\">{info.Answer}</span></label>");
            html.AppendLine($"                    <label class=\"result {(info.IsNan == 1 ? "blue" : "red")}\">{(info.IsNan == 1 ? "回答正确" : "回答错误")}</label>");
            html.AppendLine($"                </h4>");
            html.AppendLine($"                <p>{info.Content}</p>");
            html.AppendLine($"                <p {getClass(info.Answer, "A", info.SelectResult, info.IsNan == 1)} >A：{info.Aoption}</p>");
            html.AppendLine($"                <p {getClass(info.Answer, "B", info.SelectResult, info.IsNan == 1)} >B：{info.Boption}</p>");


            if (!string.IsNullOrWhiteSpace(info.Coption) && !string.IsNullOrWhiteSpace(info.Doption))
            {
                html.AppendLine($"                <p {getClass(info.Answer, "C", info.SelectResult, info.IsNan == 1)} >C：{info.Coption}</p>");
                html.AppendLine($"                <p {getClass(info.Answer, "D", info.SelectResult, info.IsNan == 1)} >D：{info.Doption}</p>");
            }
            else
            {
                // 判断题
                html.AppendLine("</br></br>");
            }
            html.AppendLine($"            </div>");
            return html.ToString();
        }

        /// <summary>
        /// 获取class样式
        /// </summary>
        /// <param name="answer"></param>
        /// <param name="option"></param>
        /// <param name="selectResult"></param>
        /// <param name="isCorrect"></param>
        /// <returns></returns>
        private string getClass(string answer, string option, string selectResult, bool isCorrect)
        {
            string Class = "";
            string[] answers = answer.Trim().Split(',');
            if (answers.Length > 1)//多选
            {
                if (answers.Contains(option))//如果答案中包括该选项
                {
                    Class = "class=\"blue\"";
                }
                else//如果答案中 不 包括该选项
                {
                    var selectResults = selectResult.Trim().Split(',');//获取选择的集合
                    var Intersect = answers.Intersect(selectResults);//获取交集
                    if (selectResult.Contains(option))
                    {
                        if (!Intersect.Contains(option)) Class = "class=\"red\"";//如果答案里面没有这个选项
                    }
                }
            }
            else//单选
            {
                if (isCorrect)//回答正确
                {
                    if (option == answer) Class = "class=\"blue\"";//回答正确的情况下，肯定都是一个选项，直接置为蓝色
                }
                else//回答错误
                {
                    if (option == selectResult) Class = "class=\"red\"";

                    if (option == answer) Class = "class=\"blue\"";
                }
            }
            return Class;
        }
    }
}
